/************************************************************************
 * @file GuiPluginActivator.cpp
 * @author Ian Chen
 * @version 1.0
 *
 * @section LICENSE
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
 * General Public License for more details at
 * http://www.gnu.org/licenses/lgpl.html
 *
 ************************************************************************/
#include <pluginui/activator/GuiPluginActivator.h>
#include <plugin/util/Framework.h>
#include <plugin/plugin/PluginFactory.h>
#include <plugin/service/LoggerService.h>
#include <plugin/util/PluginDescriptionManager.h>
#include <pluginui/manager/ConfigPanelManager.h>

namespace antu
{
namespace plugin
{
namespace ui
{
GuiPluginActivator::GuiPluginActivator(AbstractExtension *pExtension)
    : PluginActivator(),
      m_pExtension(pExtension)
{
    Q_ASSERT(pExtension != nullptr);

    QObject* pObj = (QObject*)this->m_pPluginContext->contextObjectAt(ConfigPanelManager::Name);
    this->m_pConfigPanelManager = qobject_cast<ConfigPanelManager*>(pObj);
}

GuiPluginActivator::GuiPluginActivator(PluginContext* pContext, AbstractExtension* pExtension)
    : PluginActivator(pContext),
      m_pExtension(pExtension)
{
    Q_ASSERT(pExtension != nullptr);

    QObject* pObj = (QObject*)this->m_pPluginContext->contextObjectAt(ConfigPanelManager::Name);
    this->m_pConfigPanelManager = qobject_cast<ConfigPanelManager*>(pObj);
}

GuiPluginActivator::~GuiPluginActivator()
{
    if (this->m_pExtension != nullptr)
        delete this->m_pExtension;
}

void GuiPluginActivator::init(QObject *pParent, StatusEventListener *pListener)
{
    // Get all plugin descriptions required
    vector<PluginDescriptionSharedPtr> descriptions = Framework::Instance.descriptionManager()->findAll();
    int size = descriptions.size() == 0 ? 1 : descriptions.size();
    double progressStep = 100 / 3 / size;
    double progress = 0;

    // create all plugins
    for (size_t i = 0; i < descriptions.size(); i++)
    {
        PluginDescriptionSharedPtr description = descriptions[i];
        AbstractPlugin* pPlugin = PluginFactory::Factory.createPlugin(description->code(),
                                            description,
                                            this->m_pServiceRegistry,
                                            pParent);

        GuiPlugin* pGuiPlugin = qobject_cast<GuiPlugin*>(pPlugin);
        if (pGuiPlugin != nullptr)
        {
            pGuiPlugin->setExtension(this->m_pExtension);
        }

        this->m_oPlugins.push_back(pPlugin);

        this->m_oSortedPlugins.insert(pair<QString, AbstractPlugin*>(pPlugin->code(), pPlugin));
    }

    // init plugins
    for (size_t i = 0; i < this->m_oPlugins.size(); i++)
    {
        AbstractPlugin* pPlugin = this->m_oPlugins[i];
        Framework::Instance.logger()->debug(__FILE__, __LINE__, "GuiPluginActivator", "init", "initializing " + pPlugin->description()->code());
        pPlugin->initialize(this->m_pPluginContext);

        if (this->m_pExtension != nullptr)
        {
            GuiPlugin* pGuiPlugin = qobject_cast<GuiPlugin*>(pPlugin);
            if (pGuiPlugin != nullptr)
            {
                if (this->m_pExtension->contentPanelManager() != nullptr)
                    pGuiPlugin->initContentPanel(this->m_pExtension->contentPanelManager());

                if (this->m_pExtension->sidePanelManager() != nullptr)
                    pGuiPlugin->initSidePanel(this->m_pExtension->sidePanelManager());

                if (this->m_pExtension->menuManager() != nullptr)
                    pGuiPlugin->initMenu(this->m_pExtension->menuManager());

                if (this->m_pExtension->toolBarManager() != nullptr)
                    pGuiPlugin->initToolBar(this->m_pExtension->toolBarManager());

                if (this->m_pExtension->statusBarManager() != nullptr)
                    pGuiPlugin->initStatusBar(this->m_pExtension->statusBarManager());

                pGuiPlugin->initConfigPanels(this->m_pConfigPanelManager);
            }
        }

        progress += progressStep;
        if (pListener != nullptr)
            pListener->setStatusText(QObject::tr("Loading plugins..."), (int)progress);
    }
}

void GuiPluginActivator::init(const QStringList &plugins, QObject *pParent, StatusEventListener *pListener)
{
    // Get all plugin descriptions required
    vector<PluginDescriptionSharedPtr> descriptions;
    descriptions = Framework::Instance.descriptionManager()->findAllNeededDescriptions(plugins);

    int size = descriptions.size() == 0 ? 1 : descriptions.size();
    double progressStep = 100 / 3 / size;
    double progress = 0;

    // create all plugins
    for (size_t i = 0; i < descriptions.size(); i++)
    {
        PluginDescriptionSharedPtr description = descriptions[i];
        AbstractPlugin* pPlugin = PluginFactory::Factory.createPlugin(description->code(),
                                            description,
                                            this->m_pServiceRegistry,
                                            pParent);
        this->m_oPlugins.push_back(pPlugin);

        this->m_oSortedPlugins.insert(pair<QString, AbstractPlugin*>(pPlugin->code(), pPlugin));
    }

    // init plugins
    for (size_t i = 0; i < this->m_oPlugins.size(); i++)
    {
        AbstractPlugin* pPlugin = this->m_oPlugins[i];
        Framework::Instance.logger()->debug(__FILE__, __LINE__, "GuiPluginActivator", "init", "initializing " + pPlugin->description()->code());
        pPlugin->initialize(this->m_pPluginContext);

        if (this->m_pExtension != nullptr)
        {
            GuiPlugin* pGuiPlugin = qobject_cast<GuiPlugin*>(pPlugin);
            if (pGuiPlugin != nullptr)
            {
                if (this->m_pExtension->contentPanelManager() != nullptr)
                    pGuiPlugin->initContentPanel(this->m_pExtension->contentPanelManager());

                if (this->m_pExtension->sidePanelManager() != nullptr)
                    pGuiPlugin->initSidePanel(this->m_pExtension->sidePanelManager());

                if (this->m_pExtension->menuManager() != nullptr)
                    pGuiPlugin->initMenu(this->m_pExtension->menuManager());

                if (this->m_pExtension->toolBarManager() != nullptr)
                    pGuiPlugin->initToolBar(this->m_pExtension->toolBarManager());

                if (this->m_pExtension->statusBarManager() != nullptr)
                    pGuiPlugin->initStatusBar(this->m_pExtension->statusBarManager());

                // Only root activator needs to run this
                //pGuiPlugin->initConfigPanels(this->m_pConfigPanelManager);
            }
        }

        progress += progressStep;
        if (pListener != nullptr)
            pListener->setStatusText(QObject::tr("Loading plugins..."), (int)progress);
    }
}

void GuiPluginActivator::start(StatusEventListener *pListener, bool isRootActivator/* = false*/)
{
    int size = this->m_oPlugins.size() == 0 ? 1 : this->m_oPlugins.size();
    double progressStep = 100 / 3 / size;
    double progress = 100 / 3;

    for (size_t i = 0; i < this->m_oPlugins.size(); i++)
    {
        AbstractPlugin* pPlugin = this->m_oPlugins[i];
        Framework::Instance.logger()->debug(__FILE__, __LINE__, "GuiPluginActivator", "start", "starting " + pPlugin->description()->code());
        pPlugin->start();
        Framework::Instance.logger()->debug(__FILE__, __LINE__, "GuiPluginActivator", "start", "started " + pPlugin->description()->code());

        if (this->m_pExtension != nullptr)
        {
            GuiPlugin* pGuiPlugin = qobject_cast<GuiPlugin*>(pPlugin);
            if (pGuiPlugin != nullptr)
            {
                if (this->m_pExtension->contentPanelManager() != nullptr)
                {
                    Framework::Instance.logger()->debug(__FILE__, __LINE__, "GuiPluginActivator", "start", "starting content panel for " + pPlugin->description()->code());
                    pGuiPlugin->startContentPanel(this->m_pExtension->contentPanelManager());
                }

                if (this->m_pExtension->sidePanelManager() != nullptr)
                {
                    Framework::Instance.logger()->debug(__FILE__, __LINE__, "GuiPluginActivator", "start", "starting side panel for " + pPlugin->description()->code());
                    pGuiPlugin->startSidePanel(this->m_pExtension->sidePanelManager());
                }

                if (this->m_pExtension->menuManager() != nullptr)
                {
                    Framework::Instance.logger()->debug(__FILE__, __LINE__, "GuiPluginActivator", "start", "starting menu for " + pPlugin->description()->code());
                    pGuiPlugin->startMenu(this->m_pExtension->menuManager());
                }

                if (this->m_pExtension->toolBarManager() != nullptr)
                {
                    Framework::Instance.logger()->debug(__FILE__, __LINE__, "GuiPluginActivator", "start", "starting toolbar for " + pPlugin->description()->code());
                    pGuiPlugin->startToolBar(this->m_pExtension->toolBarManager());
                }

                if (this->m_pExtension->statusBarManager() != nullptr)
                {
                    Framework::Instance.logger()->debug(__FILE__, __LINE__, "GuiPluginActivator", "start", "starting status bar for " + pPlugin->description()->code());
                    pGuiPlugin->startStatusBar(this->m_pExtension->statusBarManager());
                }

                if (isRootActivator)
                    pGuiPlugin->startConfigPanels(this->m_pConfigPanelManager);
            }
        }

        progress += progressStep;
        if (pListener != nullptr)
            pListener->setStatusText(QObject::tr("Loading plugins..."), (int)progress);
    }
}

void GuiPluginActivator::finishStartup(StatusEventListener *pListener)
{
    PluginActivator::finishStartup(pListener);

    if (this->extension() != nullptr)
    {
        if (this->extension()->contentPanelManager() != nullptr)
        {
            this->extension()->contentPanelManager()->finalize();
        }
        if (this->extension()->sidePanelManager() != nullptr)
        {
            this->extension()->sidePanelManager()->finalize();
        }
    }


}
}
}
}

